from django.conf import settings
import requests, math
import json, time, hashlib
from base64 import b64decode, b64encode
from iClouds.wePayCrypt import doSign_RSA, doSign_HMAC
from iClouds.apiheader import has_chocode
from requests.packages.urllib3.exceptions import InsecureRequestWarning
from mysqldb.models import AllinpayWxchatPos

# 禁用安全请求警告
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)

# payConf = {
#     "name": "XR新视界",
#     "mchid": "1667492159",
#     "fabric": [
#         {"name": "XR新视界", "type": "服务号", "appid": "wx959c3e8ff427eaeb"},
#         {"name": "XR新视界", "type": "小程序", "appid": "wxe5dd73be8077b6dc"},
#         {"name": "跨时空畅聊", "type": "小程序", "appid": "wxd2ba909c0fdb075c"},
#     ],
#     "certificate": "conf/WePay/apiclient_key.pem",  # 商户私钥
#     "secret": "7342BEC094F56FD86E62BCF3D6CA72B56AE6624F",
#     "apiv3": "K35WKqXHOZdKGbikq4nER4vtgVCWydkJ",
#     "notify": "https://lease.3vppt.com/api/notify/",
# }


class wxPaysRequest(requests.Session):
    """微信支付SDK"""

    # host = "https://api2.mch.weixin.qq.com"
    host = "https://api.mch.weixin.qq.com"
    notify = "https://lease.3vppt.com/api/notify/"

    def __init__(self, wxConf=3):
        super().__init__()
        self.CONF = self.hasConf(wxConf)

    def hasConf(self, idx=1):
        """查询配置"""
        try:
            r = AllinpayWxchatPos.objects.get(id=idx)
        except BaseException as err:
            return None
        else:
            return r

    def do_get(self, url="", headers=None, params=None, data=None):
        url = self.host + url
        try:
            r = self.get(url, headers=headers, params=params, data=data, verify=False)
            return r.json()
        except BaseException as err:
            return r.text

    def do_post(self, url="", headers=None, params=None, data=None, json=None):
        url = self.host + url
        try:
            r = self.post(url, headers=headers, params=params, data=data, json=json, verify=False)
            return r.json()
        except BaseException as err:
            return r.text

    def jsapi(self, kwargs):
        """jsapi | 小程序 下单, 返回prepay_id"""
        url = "/v3/pay/transactions/jsapi"
        headers = {"Content-Type": "application/json", "Accept": "application/json"}
        data = {
            "mchid": self.CONF.pay_appid,  # payConf["mchid"],  # 直连商户号
            "appid": self.CONF.apps_appid,  # payConf["fabric"][2]["appid"],  # 公众号ID|小程序ID
            "notify_url": self.notify,  # payConf["notify"],  # 通知回调地址
            "attach": "ai",  # 附加数据
            "description": kwargs["description"],  # 商品描述
            "out_trade_no": kwargs["reqsn"],  # 商户订单号
            "amount": {"total": kwargs["amount"], "currency": "CNY"},  # 订单金额
            "payer": {"openid": kwargs["openid"]},  # 支付者
            "settle_info": {"profit_sharing": True},  # 是否指定分账
        }
        #  签名认证 生成认证信息
        tamp = math.floor(time.time())  # abs(math.modf(time.time())[1])
        nstr = has_chocode(16, 1).upper()
        private_key = open(settings.BASE_DIR / self.CONF.certificate).read()
        beStr = ["POST", url, str(tamp), nstr, json.dumps(data)]
        sign = doSign_RSA(beStr, private_key)
        auth = {
            "mchid": self.CONF.pay_appid,  # payConf["mchid"]
            "serial_no": self.CONF.apiv1,  # payConf["secret"],
            "nonce_str": nstr,
            "timestamp": tamp,
            "signature": sign,
        }
        token = "WECHATPAY2-SHA256-RSA2048 "
        for k, v in auth.items():
            token += f'{k}="{v}",'
        # print(data["appid"], data["openid"])
        headers["Authorization"] = token[:-1]
        data = json.dumps(data)
        res = self.do_post(url, headers=headers, data=data)
        print(res)
        if isinstance(res, dict) and res.get("prepay_id"):
            # 构建用户数据
            r = {}
            r["timeStamp"] = str(math.floor(time.time()))
            r["nonceStr"] = has_chocode(16, 1).upper()
            r["package"] = f'prepay_id={res["prepay_id"]}'
            r["signType"] = "RSA"
            r["paySign"] = doSign_RSA(
                [
                    self.CONF.apps_appid,  # payConf["fabric"][2]["appid"],
                    r["timeStamp"],
                    r["nonceStr"],
                    r["package"],
                ],
                private_key,
            )
            r["reqsn"] = kwargs["reqsn"]
            return r
        return res

    def close(self, kwargs):
        """关闭订单"""
        out_trade_no = kwargs.get("out_trade_no")
        url = f"/v3/pay/transactions/out-trade-no/{out_trade_no}/close"
        headers = {"Content-Type": "application/json", "Accept": "application/json"}
        data = {
            "mchid": self.CONF.pay_appid,  # payConf["mchid"],  # 直连商户号
        }

        #  签名认证 生成认证信息
        tamp = math.floor(time.time())
        nstr = has_chocode(16, 1).upper()
        private_key = open(settings.BASE_DIR / self.CONF.certificate).read()
        beStr = ["POST", url, str(tamp), nstr, json.dumps(data)]
        sign = doSign_RSA(beStr, private_key)
        auth = {
            "mchid": self.CONF.pay_appid,  # payConf["mchid"]
            "serial_no": self.CONF.pay_appid.apiv1,  # payConf["secret"],
            "nonce_str": nstr,
            "timestamp": tamp,
            "signature": sign,
        }
        token = "WECHATPAY2-SHA256-RSA2048 "
        for k, v in auth.items():
            token += f'{k}="{v}",'
        headers["Authorization"] = token[:-1]
        # 开始请求通讯
        data = json.dumps(data)
        res = self.do_post(url, headers=headers, data=data)
        # print("关闭订单: ", res)
        return res  # f"关闭订单: {out_trade_no}"

    def refund(self, kwargs):
        """退款"""
        out_trade_no = kwargs.get("out_trade_no")
        url = "/v3/refund/domestic/refunds"
        headers = {"Content-Type": "application/json", "Accept": "application/json"}
        data = {
            "out_trade_no": out_trade_no,  # 原始单号
            "out_refund_no": f'AI{time.strftime("%Y%m%d%H%M%S", time.localtime())}{has_chocode(6)}',  # 退单号
            "amount": {
                "refund": kwargs.get("amount"),
                "total": kwargs.get("amount"),
                "currency": "CNY",
            },
            "notify_url": self.notify,  # 通知回调地址
            "reason": "ai",
        }

        #  签名认证 生成认证信息
        tamp = math.floor(time.time())
        nstr = has_chocode(16, 1).upper()
        private_key = open(settings.BASE_DIR / self.CONF.certificate).read()  # payConf["certificate"]
        beStr = ["POST", url, str(tamp), nstr, json.dumps(data)]
        sign = doSign_RSA(beStr, private_key)
        auth = {
            "mchid": self.CONF.pay_appid,  # payConf["mchid"]
            "serial_no": self.CONF.pay_appid.apiv1,  # payConf["secret"],
            "nonce_str": nstr,
            "timestamp": tamp,
            "signature": sign,
        }
        token = "WECHATPAY2-SHA256-RSA2048 "
        for k, v in auth.items():
            token += f'{k}="{v}",'
        headers["Authorization"] = token[:-1]

        # 开始请求通讯
        data = json.dumps(data)
        res = self.do_post(url, headers=headers, data=data)
        print("退款订单: ", res)
        return res
